/*************************************************************************
 *
 *   file		: StatisticsTimer.cs
 *   copyright		: (C) The WCell Team
 *   email		: info@wcell.org
 *   last changed	: $LastChangedDate: 2008-06-07 17:55:09 +0100 (Sat, 07 Jun 2008) $
 *   last author	: $LastChangedBy: dominikseifert $
 *   revision		: $Rev: 458 $
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WCell.Core.Timers;
using NLog;
using System.Diagnostics;
using WCell.Core;
using WCell.Constants;
using WCell.RealmServer.World;
using System.Threading;

namespace WCell.RealmServer.Statistics
{
    public class StatisticsTimer
    {
        private static Logger s_log = LogManager.GetLogger("Stats");
		private Timer m_statTimer;
        private long m_lastBytesSent, m_lastBytesReceived;
        private long m_interval;
        private PerformanceCounter m_cpuPerf, m_memUsage;

        public StatisticsTimer(long interval)
        {
            m_lastBytesSent = 0;
            m_lastBytesReceived = 0;
            m_interval = interval;

            Process thisProcess = Process.GetCurrentProcess();

            m_cpuPerf = new PerformanceCounter("Process", "% Processor Time", thisProcess.ProcessName);
            m_memUsage = new PerformanceCounter("Process", "Private Bytes", thisProcess.ProcessName);

			m_statTimer = new Timer(OnTick);
		}

		public void Start()
		{
			m_statTimer.Change(0, m_interval);
		}

        private void OnTick(object state)
        {
            StatisticsTimer timer = state as StatisticsTimer;

            List<string> statLines = new List<string>();
            float cpuUsage, memUsage;
            Process thisProcess = Process.GetCurrentProcess();

            TimeSpan processUptime = TimeSpan.FromTicks(DateTime.Now.Ticks).Subtract(TimeSpan.FromTicks(thisProcess.StartTime.Ticks));
            double averageThroughputUp, averageThroughputDown, currentThroughputUp, currentThroughputDown;

            averageThroughputUp = RealmClient.TotalBytesSent / processUptime.TotalSeconds;
            averageThroughputDown = RealmClient.TotalBytesReceived / processUptime.TotalSeconds;

            if (m_lastBytesSent == 0 || m_lastBytesReceived == 0)
            {
                m_lastBytesSent = RealmClient.TotalBytesSent;
                m_lastBytesReceived = RealmClient.TotalBytesReceived;

                currentThroughputUp = (double)m_lastBytesSent / (double)m_interval;
                currentThroughputDown = (double)m_lastBytesReceived / (double)m_interval;
            }
            else
            {
                currentThroughputUp = (double)(RealmClient.TotalBytesSent - m_lastBytesSent) / (double)m_interval;
                currentThroughputDown = (double)(RealmClient.TotalBytesReceived - m_lastBytesReceived) / (double)m_interval;
            }

            cpuUsage = m_cpuPerf.NextValue();
            memUsage = m_memUsage.NextValue();

            statLines.Add("+ Statistics --------------------------+");
            statLines.Add(string.Format("+ CPU Usage: {0:0.00}% <-> Memory Usage: {1}", cpuUsage, Statistics.FormatBytes(memUsage)));
            statLines.Add(string.Format("+ Current up: {0} <-> Current down: {1}", Statistics.FormatBytes(currentThroughputUp) + "/Sec", Statistics.FormatBytes(currentThroughputDown) + "/Sec"));
            statLines.Add(string.Format("+ Average up: {0} <-> Average down: {1}", Statistics.FormatBytes(averageThroughputUp) + "/Sec", Statistics.FormatBytes(averageThroughputDown) + "/Sec"));
            statLines.Add(string.Format("+ Thread Count: {0} <-> Players online: {1}", thisProcess.Threads.Count, WorldMgr.CharacterCount));
            statLines.Add("+ -------------------------------------+");

            foreach (string line in statLines)
            {
                s_log.Info(line);
            }
        }
    }
}
